/*
Content-Type支持的有application/www-x-form-urlencoded (a=1&b=2)
application/json ({"a":1})

如果需要上传文件 有两种方式
1. 使用表单的方式，将表单的enctype置为multipart/form-data，其实就是将Content-Type置为了←

2. 使用h5的 formData ajax上传
*/
const http = require('http');
const fs = require('fs');
const url = require('url');
const path = require('path');
const uuid = require('uuid');
//console.log(uuid.v4()); //mac地址加时间搓 全球唯一
const resolve = (filepath) => {
  return path.join(__dirname, filepath);
};

Buffer.prototype.split = function (sep) {
  const arr = [];
  const len = Buffer.from(sep).length;
  let offset = 0;
  let current;
  while (-1 !== (current = this.indexOf(sep, offset))) {
    arr.push(this.slice(offset, current));
    offset = current + len;
  }
  arr.push(this.slice(offset));
  return arr;
};

http.createServer((req, res) => {
  // 静态服务

  // 动态服务，会查询数据库
  const {pathname, query} = url.parse(req.url);

  if(pathname === '/upload' && req.method === 'POST'){
    if (req.headers['content-type'].includes('multipart/form-data')) {
      const boundary = '--' + req.headers['content-type'].split('=')[1];
      const arr = [];
      req.on('data', (chunk) => {
        // console.log('chunk:', chunk);
        arr.push(chunk);
      });
      req.on('end', () => {
        // 我们的目的是拿到 用户上传的内容 并写入到服务器本地
        const content = Buffer.concat(arr);
        const lines = content.split(boundary).slice(1,-1);
        //这里面的换行 都是/r/n 和 系统无关 是http协议规定的
        const obj = {};
        lines.forEach(line => {
          let [head, body] = line.split('\r\n\r\n');
          head = head.toString();
          const key = head.match(/name="([\s\S]+?)"/)[1]; //0是'name="username"' 1才是()里匹配的
          if(head.includes('filename')){
            //文件内容里也可能有会有\r\n\r\n，So 这里的body可能只是一部分
            const buffer = line.slice(head.length + 4);
            const filename = uuid.v4();
            const ext = head.match(/filename=[\s\S]+?(\.[^\."]+)"/)[1];
            const filepath = resolve(`upload/${filename}${ext}`);
            fs.writeFileSync(filepath, buffer);
            const statObj = fs.statSync(filepath);
            const arr = obj[key] || (obj[key] = []); //支持multiple
            arr.push({
              filename //上传到的文件路径(含文件名)
              ,filepath
              ,size:statObj.size
            });
          }else{
            body = body.toString();
            obj[key] = body.slice(0,-2); //每一行后面还有一个\r\n
          }
        });
        res.end(JSON.stringify(obj));
      });
    }
    return;
  }

  const filepath = resolve(pathname);
  fs.stat(filepath, (err, statobj) => {
    if(err){
      res.statusCode = 404;
      return res.end();
    }
    if(statobj.isFile()){
      // mime header
      return fs.createReadStream(filepath).pipe(res);
    }else{
      res.statusCode = 404;
      return res.end();
    }
  });
}).listen(3000);
